# -*- coding: utf-8 -*-
# @Time    : 2018/6/28 下午2:58
import json
import re
from contextlib import suppress
from typing import Optional

from django.http import Http404
from django.utils.deprecation import MiddlewareMixin
from django.utils.functional import SimpleLazyObject
from rest_framework import status
from rest_framework.response import Response

from social.account.models import User
from social.utils.hashid import decode_hid_with_model
from . import logger


class Ua:
    def __init__(self, browser, os, other, raw):
        self.browser = browser
        self.os = os
        self.other = other
        self.raw = raw
        self.is_hifan = 'haifan' in raw


class Browser:
    family = None
    version = None

    def __init__(self, family, version):
        self.family = family
        self.version = version


class Os:
    family = None
    version = None
    model = None

    def __init__(self, family: Optional[str], version, model):
        self.family = family and family.lower()
        self.version = version
        self.model = model


class UaOther:
    package = None
    channel = None
    build = None

    def __init__(self, package, channel, build):
        self.package = package
        self.channel = channel
        self.build = build


class InjectRequestMiddleware(MiddlewareMixin):

    def process_request(self, request):
        request._dont_enforce_csrf_checks = True
        request.os = SimpleLazyObject(lambda: self.get_os(request))
        request.ip = SimpleLazyObject(lambda: self.get_ip(request))
        request.idfa = SimpleLazyObject(lambda: self.get_idfa(request))
        request.ua = SimpleLazyObject(lambda: self.get_ua(request))
        request.did = SimpleLazyObject(lambda: self.get_did(request))
        request.uid = SimpleLazyObject(lambda: self.get_uid(request))
        request.smid = SimpleLazyObject(lambda: self.get_smid(request))
        request.is_valid = SimpleLazyObject(lambda: self.get_is_valid(request))

    def get_is_valid(self, request):
        ua = request.META.get("HTTP_USER_AGENT", "").lower()
        if not ua:
            return False
        # if not self.get_did(request):
        #     return False
        # if request.user and request.user.id and not self.get_uid(request):
        #     return False
        black_agents = ['windows']
        for agent in black_agents:
            if agent in ua:
                return False
        return True

    def get_smid(self, request):
        return request.META.get("HTTP_SMID", "")

    def get_os(self, request):
        if "ios" in request.META.get("HTTP_USER_AGENT", "").lower():
            return "ios"
        else:
            return "android"

    def get_ua(self, request):
        ua = request.META.get("HTTP_USER_AGENT", "")
        regex = "(?P<Browser_family>\S+)\/(?P<Browser_version>\S+) \((?P<Other_package>\S+); build:(?P<Other_build>\S+); (?P<Os_family>\S+) (?P<Os_version>\S+); channel:(?P<Other_channel>\S+); model:(?P<Os_model>.*?);\)"
        data = re.search(regex, ua)
        if data is None:
            browser = Browser(None, None)
            os = Os(None, None, None)
            other = UaOther(None, None, None)
        else:
            data_dict = data.groupdict()
            browser = Browser(data_dict['Browser_family'], data_dict['Browser_version'])
            os = Os(data_dict['Os_family'], data_dict['Os_version'], data_dict['Os_model'])
            other = UaOther(data_dict['Other_package'], data_dict['Other_channel'], data_dict['Other_build'])
        return Ua(browser=browser, os=os, other=other, raw=ua)

    def get_ip(self, request):
        real_ip = request.META.get("HTTP_X_REAL_IP", None)
        if real_ip:
            return real_ip
        xff = request.META.get('HTTP_X_FORWARDED_FOR', "").split(',')[0].strip()
        return xff or request.META.get('HTTP_REMOTE_ADDR', "")

    def get_uid(self, request):
        uid = request.META.get('HTTP_UID', "")
        return uid

    def get_idfa(self, request):
        idfa = request.META.get('HTTP_ADID', "")
        return idfa

    def get_did(self, request):
        return request.META.get('HTTP_DID', "")


class PrintRequestMiddleware(MiddlewareMixin):
    def process_request(self, request):
        with suppress(Exception):
            json_dict = request.GET or request.POST
            auth = request.META.get('HTTP_AUTHORIZATION')
            if json_dict:
                logger.debug(
                    f"\nRequest:{request.path}\n{auth}\n" + json.dumps(json_dict, indent=4, sort_keys=True,
                                                                       ensure_ascii=False))
            else:
                logger.debug(
                    f"\nRequest:{request.path}\n{auth}\n" + str(json.dumps(json.loads(request.body), indent=True)))


class ResponseWrapperMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        # try:
        #     response['UID'] = request.user and request.user.hid or "-"
        # except Exception:
        #     pass
        if isinstance(response, Response):
            # 客户端300以内返回数据必须要有code，message
            if response.status_code == status.HTTP_204_NO_CONTENT:
                response.status_code = status.HTTP_200_OK

            if response.status_code >= status.HTTP_400_BAD_REQUEST:
                return response
            change = False
            if response.data is None:
                response.data = {
                    'code': 0,
                    'message': 'success',
                    'data': {}
                }
                change = True
            elif isinstance(response.data, list):
                response.data = {
                    'code': 0,
                    'message': 'success',
                    "data": {"list": response.data}
                }
                change = True

            elif isinstance(response.data, dict) and "code" not in response.data.keys():
                response.data = {
                    'code': 0,
                    'message': 'success',
                    "data": response.data
                }
                change = True
            if change:
                response._is_rendered = False
                response.render()

            if isinstance(response.data, dict):
                logger.debug(json.dumps(response.data, indent=4, sort_keys=True, ensure_ascii=False))
            else:
                logger.debug(response.data)
        return response


class EncodeDecodeResponse(MiddlewareMixin):
    def process_response(self, request, response):
        return response

    def process_request(self, request):
        pass
